package com.linkhub.oms.data.sync.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.google.common.collect.Lists;
//import com.linkhub.oms.admin.common.exception.ExceptionFactory;
//import com.linkhub.oms.admin.modules.stock.domain.dto.PreemptionDTO;
//import com.linkhub.oms.admin.modules.stock.exception.PreemptionFailException;
//import com.linkhub.oms.admin.modules.stock.service.StockHandler;
import com.linkhub.oms.common.constant.WmsInfoConstant;
import com.linkhub.oms.common.enums.IEnumConvert;
import com.linkhub.oms.common.enums.mp.*;
import com.linkhub.oms.common.util.QtBeanUtil;
import com.linkhub.oms.common.util.QtStreamUtil;
import com.linkhub.oms.component.mp.util.QtMpUpdateAssist;
import com.linkhub.oms.dao.mpservice.IOrderAddressService;
import com.linkhub.oms.dao.mpservice.IOrderProductService;
import com.linkhub.oms.dao.mpservice.IOrderService;
import com.linkhub.oms.data.sync.api.shopify.domain.response.ShopOrderResponse;
import com.linkhub.oms.data.sync.enums.ShopifyOrderFinancialStatusEnum;
import com.linkhub.oms.data.sync.service.OrderSyncBizService;
import com.linkhub.oms.data.sync.util.OrderAssist;
import com.linkhub.oms.data.sync.util.OrderQueryColumnAssist;
import com.linkhub.oms.entity.OrderAddressEntity;
import com.linkhub.oms.entity.OrderEntity;
import com.linkhub.oms.entity.OrderProductEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Description: OrderSyncBizService
 * @Author: echo
 * @Date: 2024/3/29 17:03
 * @Version: 1.0
 */
@Slf4j
@Service
public class OrderSyncBizServiceImpl implements OrderSyncBizService {

    @Resource
    private IOrderService orderService;
    @Resource
    private IOrderAddressService orderAddressService;
    @Resource
    private IOrderProductService orderProductService;
//    @Resource
//    private StockHandler stockHandler;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void sync( String sysShopId, ShopOrderResponse response ) {

        List<ShopOrderResponse.Orders> orders = response.getOrders();
        List<String> orderNumbers = getOrderNumbers(orders, order -> String.valueOf(order.getOrderNumber()));
        List<OrderEntity> oldOrders = orderService.listSynchronizedShopOrders(sysShopId,
                orderNumbers, OrderQueryColumnAssist.queryOrderSyncColumns());

        List<Integer> existOrderNumbers = getOrderEntityNumbers(oldOrders);

        Map<Boolean, List<ShopOrderResponse.Orders>> saveOrUpdateMap = QtStreamUtil.partition(orders,
                order -> existOrderNumbers.contains(order.getOrderNumber()));

        handleSaveOrders(sysShopId, saveOrUpdateMap.get(false));

        handleUpdateOrders(sysShopId, saveOrUpdateMap.get(true), oldOrders);


    }

    private void handleSaveOrders( String sysShopId, List<ShopOrderResponse.Orders> orders ) {

        List<Long> orderItemVariantIds = getOrderItemVariantIds(orders);
        List<Long> matchShopSkuIds = orderProductService.listMatchShopSkuIds(sysShopId, orderItemVariantIds);
        List<OrderEntity> orderList = QtStreamUtil.map(orders,
                order -> OrderAssist.convertNewOrder(sysShopId, order, false, matchShopSkuIds));
        if (CollUtil.isEmpty(orderList)) {
            return;
        }
        List<OrderProductEntity> orderProducts = QtStreamUtil.filterAndFlatMap(orderList,
                order -> CollUtil.isNotEmpty(order.getOrderLineItems()),
                order -> order.getOrderLineItems().stream());

        List<OrderAddressEntity> orderAddressList = QtStreamUtil.filterAndMap(orderList,
                order -> Objects.nonNull(order.getOrderAddress()),
                OrderEntity::getOrderAddress);

        orderService.saveBatch(orderList);
        orderProductService.saveBatch(orderProducts);
        orderAddressService.saveBatch(orderAddressList);


    }

    private void handleUpdateOrders( String sysShopId, List<ShopOrderResponse.Orders> orders, List<OrderEntity> oldOrders ) {
        List<OrderEntity> updateOldOrders = QtStreamUtil.filter(oldOrders, order -> !order.unRenewable());
        if (CollUtil.isEmpty(updateOldOrders)) {
            return;
        }
        Map<Integer, OrderEntity> orderNumberMap = QtStreamUtil.toMap(updateOldOrders,
                order -> Integer.valueOf(order.getOrderNumber()));
        // 待更新 新订单
        List<Integer> updateOldOrderNumbers = getOrderEntityNumbers(updateOldOrders);
        List<ShopOrderResponse.Orders> pendingUpdateOrders = QtStreamUtil.filter(orders,
                order -> updateOldOrderNumbers.contains(order.getOrderNumber()));

        List<String> sysOrderIds = QtStreamUtil.map(updateOldOrders, OrderEntity::getSysOrderId);
        // 本地订单行
        List<String> localOrderLineItemOrderIds = orderProductService.listLocalOrderLineItemOrderIds(sysOrderIds);
        // 已修改的地址的订单号
        List<String> localOrderAddressOrderIds = orderAddressService.listLocalOrderAddressOrderIds(sysOrderIds);
        // 已匹配的skuId
        List<Long> matchShopSkuIds = getUpdateOrderMatchShopSkuIds(sysShopId,
                pendingUpdateOrders,
                localOrderLineItemOrderIds,
                orderNumberMap);

        // 待更新order主表数据
        List<OrderEntity> updateOrderList = QtStreamUtil.map(pendingUpdateOrders, order -> {
            OrderEntity oldOrder = orderNumberMap.get(order.getOrderNumber());
            String sysOrderId = oldOrder.getSysOrderId();
            return OrderAssist.convertUpdateOrder(order,
                    oldOrder,
                    matchShopSkuIds,
                    localOrderLineItemOrderIds.contains(sysOrderId),
                    localOrderAddressOrderIds.contains(sysOrderId));
        });

        // 待更新orderLineItems
        List<OrderProductEntity> orderProducts = QtStreamUtil.filterAndFlatMap(updateOrderList,
                order -> CollUtil.isNotEmpty(order.getOrderLineItems()),
                order -> order.getOrderLineItems().stream());
        // 待更新orderAddress
        List<OrderAddressEntity> orderAddressList = QtStreamUtil.filterAndMap(updateOrderList,
                order -> Objects.nonNull(order.getOrderAddress()),
                OrderEntity::getOrderAddress);

        orderService.updateBatchById(updateOrderList);
        // 重置物流运费
        resetOrderFreights(updateOrderList);


        orderProductService.deleteBySysOrderIds(QtStreamUtil.map(orderProducts, OrderProductEntity::getSysOrderId), OrderProductTypeEnum.THIRD_PARTY);
        orderAddressService.deleteBySysOrderIds(QtStreamUtil.map(orderAddressList, OrderAddressEntity::getSysOrderId), BoolEnum.NO);

        orderProductService.saveBatch(orderProducts);
        orderAddressService.saveBatch(orderAddressList);

        // // 如果订单最新状态为已取消，无论当前什么状态都要更新订单主表状态为已取消，地址、产品等信息无需更新
        handleUpdateDeleteOrders(orders, oldOrders);
    }

    private void handleUpdateDeleteOrders( List<ShopOrderResponse.Orders> orders, List<OrderEntity> oldOrders ) {
        List<String> cancelledOrders = orders.stream().filter(order -> {
                    // 获取订单的财务状态
                    String financialStatus = order.getFinancialStatus();
                    // 转换成 OrderStatusEnum
                    ShopifyOrderFinancialStatusEnum financialStatusEnum = IEnumConvert.valueOf(financialStatus, ShopifyOrderFinancialStatusEnum.class);
                    return ShopifyOrderFinancialStatusEnum.REFUNDED.equals(financialStatusEnum);
                }).map(ShopOrderResponse.Orders::getOrderNumber)  // 获取订单号
                .map(String::valueOf) // 将Integer转换为String
                .collect(Collectors.toList());// 将订单号收集为列表

        List<OrderEntity> updateDeleteOldOrders = QtStreamUtil.filter(oldOrders, order -> {
            // 如果订单状态为已取消或已退款，且当前状态不是已出库、追踪中,且未拆分的订单，则需要标记为已取消
            EmployeeBusinessStatusEnum employeeOrderStatus = order.getEmployeeBusinessStatus();

            return cancelledOrders.contains(order.getOrderNumber())
                    && !(EmployeeBusinessStatusEnum.OUT_OF_STORAGE.equals(employeeOrderStatus)
                    || EmployeeBusinessStatusEnum.TRACKING.equals(employeeOrderStatus))
                    && !Objects.equals(order.getSplitFlag(), BoolEnum.YES);
        });
//        List<PreemptionDTO> preemptionDTOS = Lists.newArrayList();
//        updateDeleteOldOrders.forEach(orderEntity -> {
//            orderEntity.getOrderLineItems().forEach(orderProduct -> {
//                    PreemptionDTO preemptionDTO = new PreemptionDTO();
//                    preemptionDTO.setUserId(orderEntity.getShopInfo().getUserId());
//                    preemptionDTO.setStashName(WmsInfoConstant.WAREHOUSE_CODE);
//                    preemptionDTO.setSkuId(orderProduct.getSkuId());
//                    preemptionDTO.setSkuQuantity(orderProduct.getCurrentQuantity());
//                    preemptionDTO.setBusinessType(WmsInfoConstant.XSDD);
//                    preemptionDTO.setBusinessNo(orderProduct.getSysOrderId());
//                    preemptionDTOS.add(preemptionDTO);
//            });
//        });
//        try {
//            stockHandler.orderCancel(preemptionDTOS);
//        } catch (PreemptionFailException e) {
//            throw ExceptionFactory.getI18nBizException("stock.preemption.cancel.fail");
//        }

        // 生成相应个数的 OrderEntity 列表，并设置特定属性值
        List<OrderEntity> updatedOrders = updateDeleteOldOrders.stream()
                .map(order -> {
                    order.setFinancialStatus(ShopifyOrderFinancialStatusEnum.REFUNDED.getStatus());
                    order.setOrderStatus(OrderStatusEnum.CANCELLED);
                    order.setCustomerBusinessStatus(CustomerBusinessStatusEnum.VOID);
                    order.setEmployeeBusinessStatus(EmployeeBusinessStatusEnum.CANCELLED);
                    return order;
                }).collect(Collectors.toList());
        orderService.updateBatchById(updatedOrders);
    }

    private List<Long> getUpdateOrderMatchShopSkuIds( String sysShopId,
                                                      List<ShopOrderResponse.Orders> pendingUpdateOrders,
                                                      List<String> localOrderLineItemOrderIds,
                                                      Map<Integer, OrderEntity> orderNumberMap ) {
        // 过滤出非本地订单行
        List<ShopOrderResponse.Orders> shopOrders = QtStreamUtil.filter(pendingUpdateOrders,
                order -> !localOrderLineItemOrderIds
                        .contains(orderNumberMap.get(order.getOrderNumber()).getSysOrderId()));

        List<Long> orderItemVariantIds = getOrderItemVariantIds(shopOrders);
        return orderProductService.listMatchShopSkuIds(sysShopId, orderItemVariantIds);

    }

    private List<Integer> getOrderNumbers( List<ShopOrderResponse.Orders> orders ) {
        return getOrderNumbers(orders, ShopOrderResponse.Orders::getOrderNumber);
    }

    private List<Integer> getOrderEntityNumbers( List<OrderEntity> orders ) {
        return QtStreamUtil.map(getOrderNumbers(orders, OrderEntity::getOrderNumber), Integer::valueOf);
    }

    private <T, R> List<R> getOrderNumbers( List<T> orders, Function<T, R> orderNumberFun ) {
        return QtStreamUtil.map(orders, orderNumberFun);

    }

    private List<Long> getOrderItemVariantIds( List<ShopOrderResponse.Orders> orders ) {
        List<ShopOrderResponse.Orders.LineItems> lineItems = QtStreamUtil.filterAndFlatMap(orders,
                order -> CollUtil.isNotEmpty(order.getLineItems()),
                order -> order.getLineItems().stream());

        return QtStreamUtil.map(lineItems, ShopOrderResponse.Orders.LineItems::getVariantId);
    }


    private void resetOrderFreights( List<OrderEntity> updateOrderList ) {
        List<Long> orderIds = QtStreamUtil.map(updateOrderList, OrderEntity::getId);
        if (CollUtil.isEmpty(orderIds)) {
            return;
        }
        QtMpUpdateAssist.updateWithSetNull(convertResetOrderLogistic(),
                orderService,
                wrapper -> wrapper.in(OrderEntity::getId, orderIds));
    }


    private OrderEntity convertResetOrderLogistic() {
        OrderEntity entity = new OrderEntity();
        entity.setEstimatedFreight(QtMpUpdateAssist.convertNumForUpdate(StringUtils.EMPTY));
        entity.setRegistrationFreight(QtMpUpdateAssist.convertNumForUpdate(StringUtils.EMPTY));
        return entity;
    }


}
